package moteur;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeMap;

import utils.CollectionOps;
import utils.Vector;

import utils.Index;

public class NearSearch extends NormalSearch
{	
	/**
	 *  tfitf Search
	 */
	//index
	private Index index;
	//words searched
	private ArrayList<String> words;
	private Vector  queryVec;
	
	
	public NearSearch(ArrayList<String> ws, Index i)
	{
		index = i;
		this.setQuery(ws);
	}
	
	public NearSearch(Index i)
	{
		index=i;
	}
	
	public void setQuery(ArrayList<String> ws)
	{
		words=ws;
		//the idf values for query idf values
		ArrayList<Double> queryIdf=new ArrayList<Double>();
		for(String word : words)
		{
			double idf=this.getIdf(word);
			queryIdf.add(idf);
		}
		//change queryIdf to Vector
		setQueryVec(new Vector(queryIdf));
		//queryVec.normalise();
	}
	
	public double getIdf(String word)
	{
		if(!index.hasEntry(word))
		{
			return 0.0;
		}
		//number of documents contains the word
		else
		{
			//total number of documents contains the term
			double c=index.get(word).size();
			return Math.log(index.getNbDoc()*1.0/c);
		}
		
	}
	
	public Vector getTf(String filename)
	{
		ArrayList<Double> al=new ArrayList<Double>();
		for(String word : words)
		{
			if(index.hasEntry(word))
			{
				if(index.get(word).containsKey(filename))
				{
					//get the number of occurrences in the filename for word
					al.add(1+Math.log((double) index.get(word).get(filename).size()));
					continue;
				}
			}
			al.add(0.0);
		}
		Vector re=new Vector(al);
		//re.normalise();
		return re;
	}
	
	public void rankDocs(LinkedHashSet<String> lhs,HashSet<String> filenames)
	{	
		if(filenames!=null)
		{	
			if(filenames.size()!=0)
			{
				TreeMap<Double, HashSet<String>> rankMap=new TreeMap<Double, HashSet<String>>(Collections.reverseOrder());
				for(String filename: filenames)
				{
					Vector tfVec=this.getTf(filename);
					Vector queryVec=this.getQueryVec();
					double tfitf=tfVec.multiply(queryVec);
					if(rankMap.containsKey(tfitf))
					{
						rankMap.get(tfitf).add(filename);
					}
					else
					{
						HashSet<String> hs=new HashSet<String>();
						hs.add(filename);
						rankMap.put(tfitf, hs);
					}
				}
				for(Double d : rankMap.keySet())
				{
					System.out.println(d);
					for(String filename: rankMap.get(d))
					{
						lhs.add(filename);
					}
				}
			}
		}
	}
	
	
	
	public TreeMap<Integer, HashSet<String> > getPriorityList()
	{
		HashSet<String> resultUnion=new HashSet<String>();
		//HashSet<String> resultIntersection=null;
		
		//if(words.size()!=0)
		//	resultIntersection=new HashSet<String>(index.get(words.get(0)).keySet());
		
		for(String word: words)
		{
			if(index.hasEntry(word))
			{
				resultUnion=CollectionOps.union(resultUnion,index.get(word).keySet());
				//System.out.print(resultUnion.size());
				//resultIntersection=CollectionOps.intersection(resultIntersection,
				//			index.get(word).keySet());
			}
		}
		
		TreeMap<Integer, HashSet<String> > nbOccurrence=new TreeMap<Integer, HashSet<String> >(Collections.reverseOrder());
		for(String filename: resultUnion)
		{
			int occurs=0;
			for(String word :words)
			{
				if(index.hasEntry(word)&&index.get(word).containsKey(filename))
					occurs++;
			}
			if(!nbOccurrence.containsKey(occurs))
			{
				nbOccurrence.put(occurs, new HashSet<String>());
			}
			nbOccurrence.get(occurs).add(filename);
				
		}
		return nbOccurrence;
	}
	
	@Override
	public void print() {
		// TODO Auto-generated method stub
		System.out.print("NearSearch: ");
		System.out.println(words);
	}

	public Vector getQueryVec() {
		return queryVec;
	}

	public void setQueryVec(Vector queryVec) {
		this.queryVec = queryVec;
	}

	
	
}
